#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
系统恢复和错误处理模块
提供自动恢复、错误重试、资源清理等功能
"""

import time
import threading
import traceback
from functools import wraps
from .config import setup_logging

class RecoveryManager:
    """恢复管理器"""
    
    def __init__(self):
        self.logger = setup_logging('Recovery')
        self.retry_counts = {}
        self.max_retries = 3
        self.retry_delay = 5
        self.recovery_callbacks = {}
        
    def register_recovery_callback(self, component_name, callback):
        """注册组件恢复回调"""
        self.recovery_callbacks[component_name] = callback
    
    def attempt_recovery(self, component_name, error):
        """尝试恢复组件"""
        self.logger.warning(f"尝试恢复组件: {component_name}, 错误: {error}")
        
        # 检查重试次数
        retry_count = self.retry_counts.get(component_name, 0)
        if retry_count >= self.max_retries:
            self.logger.error(f"组件 {component_name} 重试次数已达上限")
            return False
        
        # 增加重试计数
        self.retry_counts[component_name] = retry_count + 1
        
        # 延迟重试
        time.sleep(self.retry_delay)
        
        # 执行恢复回调
        if component_name in self.recovery_callbacks:
            try:
                success = self.recovery_callbacks[component_name]()
                if success:
                    self.logger.info(f"组件 {component_name} 恢复成功")
                    self.retry_counts[component_name] = 0  # 重置计数
                    return True
                else:
                    self.logger.error(f"组件 {component_name} 恢复失败")
                    return False
            except Exception as e:
                self.logger.error(f"恢复回调执行失败: {e}")
                return False
        else:
            self.logger.error(f"未找到组件 {component_name} 的恢复回调")
            return False
    
    def reset_retry_count(self, component_name):
        """重置重试计数"""
        if component_name in self.retry_counts:
            self.retry_counts[component_name] = 0
            self.logger.info(f"重置组件 {component_name} 的重试计数")

# 全局恢复管理器实例
recovery_manager = RecoveryManager()

def with_recovery(component_name, auto_retry=True):
    """装饰器：为函数添加错误恢复机制"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                logger = setup_logging('Recovery')
                logger.error(f"函数 {func.__name__} 执行失败: {e}")
                logger.error(f"错误详情: {traceback.format_exc()}")
                
                if auto_retry:
                    success = recovery_manager.attempt_recovery(component_name, e)
                    if success:
                        # 恢复成功，重新尝试执行
                        try:
                            return func(*args, **kwargs)
                        except Exception as retry_error:
                            logger.error(f"重试执行失败: {retry_error}")
                            raise retry_error
                    else:
                        raise e
                else:
                    raise e
        return wrapper
    return decorator

def safe_execute(func, *args, **kwargs):
    """安全执行函数，捕获并记录异常"""
    logger = setup_logging('SafeExecute')
    try:
        return func(*args, **kwargs)
    except Exception as e:
        logger.error(f"安全执行失败: {func.__name__}, 错误: {e}")
        logger.error(f"错误详情: {traceback.format_exc()}")
        return None

class ResourceManager:
    """资源管理器"""
    
    def __init__(self):
        self.logger = setup_logging('ResourceManager')
        self.resources = {}
        self.cleanup_callbacks = []
    
    def register_resource(self, name, resource, cleanup_func=None):
        """注册资源"""
        self.resources[name] = {
            'resource': resource,
            'cleanup': cleanup_func
        }
    
    def cleanup_resource(self, name):
        """清理指定资源"""
        if name in self.resources:
            resource_info = self.resources[name]
            if resource_info['cleanup']:
                try:
                    resource_info['cleanup'](resource_info['resource'])
                    self.logger.info(f"清理资源成功: {name}")
                except Exception as e:
                    self.logger.error(f"清理资源失败: {name}, 错误: {e}")
            del self.resources[name]
    
    def cleanup_all(self):
        """清理所有资源"""
        self.logger.info("开始清理所有资源")
        for name in list(self.resources.keys()):
            self.cleanup_resource(name)
        
        # 执行额外的清理回调
        for callback in self.cleanup_callbacks:
            try:
                callback()
            except Exception as e:
                self.logger.error(f"清理回调执行失败: {e}")
        
        self.logger.info("资源清理完成")
    
    def register_cleanup_callback(self, callback):
        """注册清理回调"""
        self.cleanup_callbacks.append(callback)

# 全局资源管理器实例
resource_manager = ResourceManager()

class HealthChecker:
    """健康检查器"""
    
    def __init__(self, check_interval=30):
        self.logger = setup_logging('HealthChecker')
        self.check_interval = check_interval
        self.health_checks = {}
        self.running = False
        self.check_thread = None
    
    def register_health_check(self, name, check_func, recovery_func=None):
        """注册健康检查"""
        self.health_checks[name] = {
            'check': check_func,
            'recovery': recovery_func,
            'last_check': 0,
            'status': 'unknown'
        }
    
    def start(self):
        """启动健康检查"""
        if self.running:
            return
        
        self.running = True
        self.check_thread = threading.Thread(target=self._check_loop)
        self.check_thread.daemon = True
        self.check_thread.start()
    
    def stop(self):
        """停止健康检查"""
        self.running = False
        if self.check_thread:
            self.check_thread.join(timeout=5)
        self.logger.info("健康检查已停止")
    
    def _check_loop(self):
        """检查循环"""
        while self.running:
            try:
                for name, check_info in self.health_checks.items():
                    self._perform_check(name, check_info)
                time.sleep(self.check_interval)
            except Exception as e:
                self.logger.error(f"健康检查循环错误: {e}")
                time.sleep(5)
    
    def _perform_check(self, name, check_info):
        """执行单个检查"""
        try:
            is_healthy = check_info['check']()
            check_info['last_check'] = time.time()
            
            if is_healthy:
                check_info['status'] = 'healthy'
            else:
                check_info['status'] = 'unhealthy'
                
                # 尝试恢复
                if check_info['recovery']:
                    try:
                        recovery_success = check_info['recovery']()
                        if recovery_success:
                            self.logger.info(f"组件 {name} 恢复成功")
                        else:
                            self.logger.error(f"组件 {name} 恢复失败")
                    except Exception as e:
                        self.logger.error(f"组件 {name} 恢复过程中出错: {e}")
        
        except Exception as e:
            self.logger.error(f"健康检查 {name} 执行失败: {e}")
            check_info['status'] = 'error'
    
    def get_status(self):
        """获取所有组件的健康状态"""
        status = {}
        for name, check_info in self.health_checks.items():
            status[name] = {
                'status': check_info['status'],
                'last_check': check_info['last_check']
            }
        return status

# 全局健康检查器实例
health_checker = HealthChecker()

def cleanup_on_exit():
    """程序退出时的清理函数"""
    logger = setup_logging('Cleanup')
    logger.info("程序退出，开始清理资源")
    
    # 停止健康检查
    health_checker.stop()
    
    # 清理所有资源
    resource_manager.cleanup_all()
    
    logger.info("清理完成")

# 注册退出清理
import atexit
atexit.register(cleanup_on_exit)